
import { _decorator, Component, Node, game, sys } from 'cc';
import { Constants } from '../configs/Constants';
import { IGameHttpRequest } from '../donet/doHttp';
import { DoNetManager } from '../donet/doNetManager';
import { E2LProtocol, L2EProtocol } from '../proto/ELProtocol';
import { CustomEventListener } from './CustomEventListener';
import { GameData } from "./GameData";

const { ccclass, property } = _decorator;
const EventName = Constants.EventName;
 
enum APP_STATE {
    welcome = 1,
    hall,
    game
}

@ccclass('LogicCenter')
export class LogicCenter extends Component {

    private netManager: DoNetManager = null;
    private gameData: GameData = null;

    private appState: APP_STATE = APP_STATE.welcome;

    onLoad() {
        game.addPersistRootNode(this.node);

        this.netManager = new DoNetManager();
        this.gameData = new GameData();

        this.switchState(APP_STATE.welcome);

        CustomEventListener.on(E2LProtocol.e2l_start_login, this.startLogin, this);
        CustomEventListener.on(L2EProtocol.l2e_login_with_pw, this.loginWithPW, this);
        CustomEventListener.on(L2EProtocol.l2e_reg_with_pw, this.registeAccount, this);

        
        CustomEventListener.on(EventName.READ_CONFIGS, this.readConfigs, this);
        CustomEventListener.on(EventName.HTTP_REQUEST, this.httpRequest, this);
        CustomEventListener.on(EventName.CONN_WS, this.connectWebSocket, this);
        CustomEventListener.on(EventName.WS_REQ_PB, this.wsRequestPB, this);
        CustomEventListener.on(EventName.WS_CANCEL_CONFIRM, this.wsCancelConfirm, this);

        CustomEventListener.on(EventName.LOGIN_ERROR, this.loginErrorHandle, this);
        
        CustomEventListener.on("core_notify_ws_response", this.webSockDataHandle.bind(this));
        CustomEventListener.on("core_notify_http_response_successful", this.httpSuccHandle, this);
        CustomEventListener.on("core_notify_http_response_failed", this.httpFailHandle, this);
        CustomEventListener.on("core_notify_http_response_failed_401", this.startLogin, this);

        
    }
    
    // update (deltaTime: number) {
    //     // [4]
    // }
    
    onDestroy() {
        CustomEventListener.off(E2LProtocol.e2l_start_login, this.startLogin, this);
        CustomEventListener.off(L2EProtocol.l2e_login_with_pw, this.loginWithPW, this);
        CustomEventListener.off(L2EProtocol.l2e_reg_with_pw, this.registeAccount, this);

        CustomEventListener.off(EventName.READ_CONFIGS, this.readConfigs, this);
        CustomEventListener.off(EventName.HTTP_REQUEST, this.httpRequest, this);
        CustomEventListener.off(EventName.CONN_WS, this.connectWebSocket, this);
        CustomEventListener.off(EventName.WS_REQ_PB, this.wsRequestPB, this);
        CustomEventListener.off(EventName.WS_CANCEL_CONFIRM, this.wsCancelConfirm, this);

        CustomEventListener.off(EventName.LOGIN_ERROR, this.loginErrorHandle, this);

        CustomEventListener.off("core_notify_ws_response", this.webSockDataHandle, this);
        CustomEventListener.off("core_notify_http_response_successful", this.httpSuccHandle, this);
        CustomEventListener.off("core_notify_http_response_failed", this.httpFailHandle, this);
        CustomEventListener.off("core_notify_http_response_failed_401", this.startLogin, this);

        this.gameData = null;

        this.netManager = null;
        
    }
    
    private readConfigs() {

    }

    private startLoad() {

    }

    private switchState(nextState: APP_STATE) {
        this.enterState(nextState);
        this.exitState();
        this.appState = nextState;
    }

    private enterState(nextState: APP_STATE) {
        switch (nextState) {
            case APP_STATE.welcome:
                
                break;
        
            default:
                break;
        }
    }

    private exitState() {
        switch (this.appState) {
            case APP_STATE.welcome:
                
                break;
        
            default:
                break;
        }
    }

    private httpRequest(eventName: string, url: string, method: string, data: string, headersVal: any) {
        let request : IGameHttpRequest = {
            eventName: eventName,
            url: url,
            method: method,
            reqData: data,
        }
        // POST时header有特殊要求
        let headers = {};
        if (request.method === "POST") {
            headers["Content-Type"] = "application/x-www-form-urlencoded";
            if (globalThis.account_token && globalThis.account_token !== "undefined") {
                headers["user-token"] = globalThis.account_token;
            }
        }
        for (var key in headersVal) {
            var header = headersVal[key];
            if (!header) continue;
            console.log("http request header 【" + key + "】 : " + JSON.stringify(header));
            headers[key] = header;
        }
        request.header = headers;

        this.netManager.httpRequest(request);
    }

    private httpSuccHandle(response: any) {
        let eventName = response["event_name"];
        let data = response["response_data"];
        let code = response["response_code"];

        if (eventName === "login_account") {
            this.gameData.loginComplete(data.data);
        } else if (eventName === "ws_addr_request") {
            this.gameData.wsAddrResponse(data.data);
        } else if (eventName === "registe_account") {

        }
    }

    private httpFailHandle(response: any) {
        let eventName = response["event_name"];
        let data = response["response_data"];
        let code = response["response_code"];

        let self = this;

        if (eventName === "ws_addr_request") {
            Constants.center_server_url = "";
            if (!code || code < 0) {
                var continue_fun = function () {
                    self.gameData.wsAddrRequest();
                }
                CustomEventListener.dispatchEvent(L2EProtocol.l2e_open_msg_box, {
                    "type": Constants.BOX_BTN_TYPE.continue,
                    "text": response || "没有网关信息，无法连接游戏！\n点击【确定】重新连接？",
                    "continue_fun": continue_fun,
                    "fairy": 1
                });
                return;
            } else if (code === 601) {
                this.gameData.resetReloginCount();
                this.gameData.doInvalidToken();
            } else {
                CustomEventListener.dispatchEvent(L2EProtocol.l2e_open_msg_box, {
                    "type": Constants.BOX_BTN_TYPE.know,
                    "text": response || "获取ws地址失败",
                    "fairy": 1
                });
            }
        } else if (eventName === "login_account") {
            this.gameData.doInvalidToken();
        } else if (eventName === "registe_account"){
            // 注册失败，清除数据
            localStorage.setItem("local_last_login_account", "");
            localStorage.setItem("local_last_login_password", "");
        }

        CustomEventListener.dispatchEvent(L2EProtocol.l2e_open_msg_box, {
            "type": Constants.BOX_BTN_TYPE.toast,
            "text": response || "~请求失败，请稍后再试~",
        });

    }

    private connectWebSocket(url: string, succFunc: Function, failFunc: Function) {
        this.netManager.connectWebSock(url, succFunc, failFunc);
    }

    private wsRequestPB(data : IRequestProto) {
        this.netManager.webSockRequestPB(data);
    }

    private wsCancelConfirm() {
        this.netManager.cancelWebSockConfirm();
    }

    private webSockDataHandle(event: any) {
        let self = this;
        let eventName = event["event_name"];
        let response_data = event["response_data"];
        let response_code = event["response_code"];

        if (COMMON_PB_COMMAND.MSG_CONFIRM_REQUEST == eventName) {
            let code = response_code || 0;
            if (code === 8) {
                console.warn("认证ws 异常-->跳转登录 code " + code);
                // g_notifyer.notify_frame_event("quit_to_login");
                CustomEventListener.dispatchEvent(L2EProtocol.l2e_show_login);
                return;
            }
            globalThis.login_inTable = (response_data.inTable || false);                            // 是否在桌子中
            if (code != 0) {
                self.gameData.doInvalidToken();
                return;
            }

            // 获取用户信息
            self.gameData.doRequestUserinfo();
        } else if (COMMON_PB_COMMAND.MSG_GET_USER_INFO_REQUEST) {
            self.gameData.parseUserInfo(response_data);
            if (self.appState === APP_STATE.welcome) {
                this.switchState(APP_STATE.hall);
            }
        }
    }

    // private welcomeOver(){
    //     // todo 冷更或热更
    //     // 登录逻辑
    //     this.startLogin();
    // }

    private startLogin() {
        this.gameData.resetReloginCount();
        if (this.gameData.checkToken() === false) {
            // 无效token
            this.gameData.doInvalidToken();
        } else {
            // 拿登录信息
            this.gameData.doLogin();
        }
    }

    private loginWithPW(account: string, password: string) {
        this.gameData.resetReloginCount();
        this.gameData.doLogin(account, password);
        localStorage.setItem("local_last_login_type", "pw");
        localStorage.setItem("local_last_login_account", account);
        localStorage.setItem("local_last_login_password", password);
    }

    private registeAccount(account: string, password: string, validCode: string) {
        this.gameData.doRegiste(account, password, validCode);
        localStorage.setItem("local_last_login_type", "pw");
        localStorage.setItem("local_last_login_account", account);
        localStorage.setItem("local_last_login_password", password);
    }

    // private logResLoaded = false;
    private loginErrorHandle(code: number) {
        // if (this.logResLoaded === true) {
            // todo code > 0统统转登录界面
            CustomEventListener.dispatchEvent(L2EProtocol.l2e_show_login);
        // }
    }

    private checkLogAfterLoad() {
        if (this.gameData.isReady2Game() === true) {
            // todo 资源与游戏数据都备好，进游戏
            return;
        }
        if (this.gameData.isReady2Hall() === true) {
            // todo 资源与数据都备好，进大厅
        }
    }
}
